class Mvvm {


  constructor(el, obj) {
    this.el = document.querySelector(el);
    // 用于保存原始数据
    // this._data = obj.data;
    this.data = obj.data;
    this.domPool = {};

    // 初始化
    this.init();
  }

  init() {
    // 第一步，数据响应式，obj.defineProperty || new Proxy
    // 第二步，监听绑定了v-model的input的输入，并获取input的value值，使其改变本地value数据
    // 第三部，让相关的dom节点({{}}节点)，实时相应。

    this.initData();
    this.initDom();
  }

  initData() {
    // this.data = {};
    const _this = this;

    // for (let key in this._data) {
    //   Object.defineProperty(this.data, key, {
    //     // 获取数据
    //     get() {
    //       return _this._data[key];
    //     },
    //     // 设置数据
    //     set(newValue) {
    //       // 数据变化事件发生，通知改变
    //       _this._data[key] = newValue;
    //       _this.domPool[key].forEach(node => {
    //         node.nodeValue = newValue;
    //       })
    //     }
    //   })
    // }

    this.data = new Proxy(this.data, {
      get(target, key) {
        return Reflect.get(target, key);
      },
      set(target, key, value) {
        _this.domPool[key].forEach(node => {
          node.nodeValue = value;
        })
        return Reflect.set(target, key, value);
      }
    })
  }
  /**
   * 接受element，找到该element下所有含有v-model的input
   * @param {HTMLElement} el 
   */
  bindInput(el = this.el) {
    const allInput = el.querySelectorAll('input');
    allInput.forEach(input => {
      const v_model = input.getAttribute('v-model');
      if (v_model) {
        input.addEventListener('change', this.handleInput.bind(this, v_model, input), false);
        input.addEventListener('keyup', this.handleInput.bind(this, v_model, input), false);
      }
    });
  }
  /**
   * input中的数据改变，需要引起mvvm中的数据data同时改变
   * @param {Mvvm} mvvm 
   * @param {String} v_model 
   * @param {HTMLInputElement} input 
   */
  handleInput(v_model, input) {
    const value = input.value;
    this.data[v_model] = value;
  }

  /**
   * 递归查找所有节点，判断文本节点内是否包含 {{}} 形式的字符串
   * @param {HTMLElement} el 
   */
  bindDom(el = this.el) {
    // 子节点
    const childNodes = el.childNodes;
    childNodes.forEach(node => {
      // nodeType === 3 文本节点
      if (node.nodeType === 3) {
        const value = node.nodeValue;
        // 存在元素内容
        if (value.trim().length) {
          let isValid = /\{\{(.+?)\}\}/.test(value);
          if (isValid) {
            const v_model = value.match(/\{\{(.+?)\}\}/)[1].trim();
            if (this.domPool[v_model]) {
              this.domPool[v_model].push(node);
            } else {
              this.domPool[v_model] = [node];
            }
            node.nodeValue = this.data[v_model] ?? 'undefined';
          }
        }
      }

      if (node.hasChildNodes) {
        this.bindDom(node);
      }
    });
  }

  initDom() {
    this.bindInput();
    this.bindDom();
  }

  /**
   * 设置Mvvm的data中key的值为value
   * @param {String} key 
   * @param {String} value 
   */
  setData(key, value) {
    this.data[key] = value;
  }


}